package myJs.tool

import scala.scalajs.js.Dynamic.{global => g}
import myJs.myPkg.{BootstrapValidator, DatepickerOptions, MiniColorsOptions}
import myJs.myPkg.jquery.{$, JQuery}
import scalatags.Text.all._

import scala.scalajs.js
import myJs.Implicits._
import org.scalajs.dom.{Element, PerformanceNavigation, document}
import org.scalajs.dom.ext.Ajax
import shared._

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js.{Date, UndefOr}
import myJs.myPkg.bootstrap.Bootstrap.default._
import myJs.tool.Tool._

import scala.concurrent.Future
import myJs.Implicits._

/**
 * Created by yz on 20/7/2020
 */
trait ProjectTool {

  def showChange(y: Element, f: String => Boolean, showJq: JQuery) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    if (f(myValue)) {
      showJq.show()
    } else {
      showJq.hide()
    }
  }

  def getTabIdWithPrefix(tabId: String, prefix: String) = {
    if (prefix.isBlank) tabId else s"${prefix.toLowerCase}${tabId.capitalize}"
  }

  def getTabJqWithPrefix(tabId: String, prefix: String) = {
    val finalTabId = getTabIdWithPrefix(tabId, prefix)
    $(s"#${finalTabId}")
  }

  def getFileSize(v: js.Any) = {
    v.toString.toInt match {
      case x if x < 1024 =>
        s"${x}B"
      case x if x >= 1024 && x < 1024 * 1024 =>
        s"${x / 1024}KB"
      case x if x >= 1024 * 1024 && x < 1024 * 1024 * 1024 =>
        s"${x / (1024 * 1024)}MB"
    }
  }

  def dateInit = {
    val options = DatepickerOptions(format=Tool.pattern,autoclose=true,forceParse=true)
    $(".myDatepicker").datepicker(options)
  }

  def fileNameA(v: js.Any, row: JDJAn) = {
    val url = g.jsRoutes.controllers.DataController.detailBefore().url.toString
    a(href := s"${url}?id=${row("id")}", target := "_blank", s"${v.toString}")
  }

  def getCurTabId = {
    $(".myMainUl li.active a").attr("href").get.replaceAll("^#", "")
  }

  def getCurTabId(parentJq: JQuery) = {
    parentJq.find(".myMainUl li.active a").attr("href").get.replaceAll("^#", "")
  }

  def getValues(inY: Element) = {
    if ($(inY).hasClass("select2MultiInput")) {
      if ($(inY).data("select2").isDefined) {
        $(inY).select2Val
      } else js.Array[String]()
    } else {
      $(inY).myVal.toMyArray
    }
  }

  def getMissionId = {
    g.missionId.toString
  }

  def toggle2Boolean(formJq: JQuery) = {
    formJq.find(s".myToggle").foreach { y =>
      if (!$(y).isChecked) {
        val html = input(`type` := "hidden", name := $(y).nameAttr, value := s"false")
        $(y).after(html.render)
      }
    }
  }

  def getGroupVsMap(groups: List[String]) = {
    val groupVs = getGroupVs(groups)
    groupVs.map { x =>
      (x, x)
    }.toSeqMap
  }

  def getGroups = {
    val jq = Tool.getInputByName("groupFile")
    val fileName = jq.myVal
    if (jq.isVisible && fileName.nonEmpty) {
      val dataFile = Tool.getInputByName("file").myVal
      val url = g.jsRoutes.controllers.GroupFileDataController.getGroups().url.toString
      Ajax.get(url = s"${url.noCache}&groupFile=${fileName.encodeURI}&file=${dataFile.encodeURI}",
        headers = Map("Content-Type" -> "application/json")).map { xhr =>
        xhr.responseText.toJArS.toList
      }
    } else {
      Future {
        List[String]()
      }
    }
  }

  def getConfigJsonData(idStr: String = "") = {
    val fileName = "config.json"
    val missionId = Tool.getMissionId
    val url = g.jsRoutes.controllers.MissionToolController.getConfigJsonData().url.toString
    Ajax.get(url = s"${url.noCache}&missionId=${getMissionId}&fileName=${fileName}&idStr=${idStr}",
      headers = Map("Content-Type" -> "application/json")).map { xhr =>
      xhr.responseText.toJDJAn
    }
  }

  def getGroupVs(groups: List[String]) = {
    groups.combinations(2).map { groups =>
      val group1 = groups(0)
      val group2 = groups(1)
      s"${group1}-${group2}"
    }.toList
  }

  def refreshCalculateConfigByJsonFile(f: JDJAn => Any = x => ()) = {
    val missionId = getMissionId
    if (missionId.nonBlank) {
      val url = g.jsRoutes.controllers.MissionController.getConfigData().url.toString
      Ajax.get(url = s"${url.noCache}&missionId=${missionId}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
        val rawRs = xhr.responseText.toJDJAn
        val rs = rawRs.toMyJDS
        Tool.fillByNames(rs)
        Tool.fillByNameAndTriggers(rawRs)
        $(".myFile").foreach { y =>
          val name = $(y).nameAttr
          $("#form").bv.revalidateField(name)
        }
        f(rawRs)
      }
    }
  }

  def refreshCalculateConfig(f: JDS => Any = x => ()) = {
    val fileName = "calculate_config.txt"
    val missionId = Tool.getMissionId
    if (missionId.nonEmpty) {
      val url = g.jsRoutes.controllers.MissionToolController.getConfigData().url.toString
      Ajax.get(url = s"${url.noCache}&missionId=${getMissionId}&fileName=${fileName}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
        val rs = xhr.responseText.toJDJAn.toMyJDS
        Tool.fillByNames(rs)
        Tool.fillByNameAndTriggers(rs.toJDJAn)
        $(".myFile").foreach { y =>
          val name = $(y).nameAttr
          $("#form").bv.revalidateField(name)
        }
        f(rs)
      }
    }
  }

  def setDisable(parentId: String = "") = {
    val parentElem = Tool.getParentElem(parentId)
    val size = $(s"${parentElem} .eachColor").mapElems(y => y).size
    size match {
      case x if x <= 2 =>
        $(s"${parentElem} .deleteButton").setDisabled(true)
        $(s"${parentElem} .myAddColor").setDisabled(false)
      case x if x > 2 && x < 6 =>
        $(s"${parentElem} .deleteButton").setDisabled(false)
        $(s"${parentElem} .myAddColor").setDisabled(false)
      case x if x >= 6 =>
        $(s"${parentElem} .deleteButton").setDisabled(false)
        $(s"${parentElem} .myAddColor").setDisabled(true)
    }
  }

  def deleteColor(y: Element, parentId: String) = {
    $(y).parents(".eachColor").remove()
    $(s"#${parentId} #form").bv.revalidateField("customColors[]")
    Tool.setDisable(parentId)
  }

  def dateTimeFormat(time: Date, showYear: Boolean = true) = {
    val year = time.getFullYear().toInt
    val month = time.getMonth().toInt + 1
    val day = time.getDate().toInt
    val hour = time.getHours().toInt
    val minute = time.getMinutes().toInt
    val second = time.getSeconds().toInt
    if (showYear) {
      s"${year}-${zeroFill(month)}-${zeroFill(day)} ${zeroFill(hour)}:${zeroFill(minute)}:${zeroFill(second)}"
    } else {
      s"${zeroFill(month)}-${zeroFill(day)} ${zeroFill(hour)}:${zeroFill(minute)}:${zeroFill(second)}"
    }
  }

  def zeroFill(int: Int) = {
    if (int < 10) s"0${int}" else int.toString
  }

  def selectTab(tabId: String) = {
    $("#myUl>li").removeClass("active")
    $(s"#myUl").find(s"a[href='#${tabId}']").parent("li").addClass("active")
    $(s"#${tabId}").siblings().removeClass("active in")
    $(s"#${tabId}").addClass("active in")
  }

  def selectArgTab(tabId: String) = {
    $(s"a[href='#${tabId}']").parent().siblings().removeClass("active")
    $(s"a[href='#${tabId}']").parent("li").addClass("active")
    $(s"#${tabId}").siblings().removeClass("active in")
    $(s"#${tabId}").addClass("active in")
  }

  def myToggle(tabJq: JQuery) = {
    tabJq.find(s"#content").toggleClass("col-sm-12 col-sm-8")
    tabJq.find(s"#sidebar").toggleClass("collapsed")
    tabJq.find(s".myToggle i").toggleClass("fa-angle-double-right fa-angle-double-left")
  }

  def groupFileChange = {
    val jq = Tool.getInputByName("groupFile")
    val dataFile = Tool.getInputByName("file").myVal
    val fileName = jq.myVal
    if (jq.isVisible && fileName.nonEmpty) {
      val url = g.jsRoutes.controllers.GroupFileDataController.getGroupNum().url.toString
      Ajax.get(url = s"${url.noCache}&groupFile=${fileName.encodeURI}&file=${dataFile.encodeURI}",
        headers = Map("Content-Type" -> "application/json")).map { xhr =>
        val groupNum = xhr.responseText.toInt
        if (groupNum == 2) {
          $("#twoGroup").show()
          $("#mulGroup").hide()
        } else {
          $("#twoGroup").hide()
          $("#mulGroup").show()
        }
      }
    } else {
      $("#twoGroup").hide()
      $("#mulGroup").hide()
    }

  }

  def showIsPaired = {
    val jq = Tool.getInputByName("groupFile")
    val dataFile = Tool.getInputByName("file").myVal
    val group = Tool.getInputByName("group").myVal
    if (jq.isVisible) {
      val groupFile = jq.myVal
      if (groupFile.nonEmpty && dataFile.nonEmpty) {
        val url = g.jsRoutes.controllers.GroupFileDataController.isPaired().url.toString
        Ajax.get(url = s"${url.noCache}&groupFile=${groupFile.encodeURI}&file=${dataFile.encodeURI}&group=${group}",
          headers = Map("Content-Type" -> "application/json")).map { xhr =>
          val b = xhr.responseText.toBoolean
          if (b) {
            $("#isPaired").show()
          } else {
            Tool.getInputByName("isPaired").bootstrapToggle("off")
            $("#isPaired").hide()
          }
        }
      }
    } else {
      Tool.getInputByName("isPaired").bootstrapToggle("off")
      $("#isPaired").hide()
    }
  }

  def colorChange: js.Function = (value: UndefOr[String], opacity: UndefOr[Double]) => {
    if (opacity.isDefined) {
      s"${value.get},${opacity.get}"
    } else {
      value.get
    }
  }

  def initMiniColors = {
    val swatches = js.Array("#00ff00", "#FFFFFF", "#a5d6a7", "#fff59d",
      "#ffcc80", "#bcaaa4", "#eeeeee", "#f44336", "#2196f3", "#4caf50", "#ffeb3b", "#ff9800", "#795548", "#9e9e9e")
    val options = MiniColorsOptions.control("hue").format("hex").swatches(swatches).theme("bootstrap").inline(false).
      letterCase("lowercase").position("bottom").keywords("").change(Tool.colorChange).
      opacity(false)
    $(".myMinicolors").minicolors(options)
  }

  def refreshColor(tabId: String, kind: String = "", idStr: String = "") = {
    val url = g.jsRoutes.controllers.MissionToolController.getColorData().url.toString
    Ajax.get(url = s"${url.noCache}&missionId=${Tool.getMissionId}&kind=${kind}&idStr=${idStr}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJDJAn.toMyJDS
      if (rs.size > 1) {
        $("#legend").show()
      } else {
        $("#legend").hide()
      }
      val colorHtml = rs.map { case (group, color) =>
        div(`class` := "form-group",
          label(`class` := "control-label col-sm-4", group),
          div(`class` := "col-sm-8",
            input(`type` := "text", name := "colors[]", `class` := "form-control myMinicolors", value := color)
          )
        )
      }.mkString("&nbsp;")
      $(s"#${tabId} #colors").html(colorHtml)
      Tool.initMiniColors
      Tool.getInputByName("colors[]").foreach { y =>
        $(y).minicolors("value", js.Dictionary("color" -> s"${$(y).myVal}"))
      }
    }
  }

  def fileSelect(folder: String, fileName: String) = {
    val formId = "form"
    val fileModalId = "fileModal"
    val inputJq = $(".myFileSelect.myCurrent").parent().prev().find("input")
    inputJq.`val`(s"${folder}/${fileName}")
    $("#form").bv.revalidateField(inputJq)
    $(s"#${fileModalId}").modal("hide")
  }

}
